<?php

namespace StarCloud\Library;

use Framework\DiServices\HttpClient;
use Phalcon\Di;

class KuaiShou
{
    protected $appId;
    protected $secret;
    protected $access_token;

    protected $httpClient;
    protected $cacheClass;

    const REFUND_CALLBACK = 'https://api.doumvip.com/api/ks_order/refund_call';

    const API_URL_PREFIX = 'https://open.kuaishou.com';
    const AUTH_URL = '/oauth2/access_token?';
    const REPORT_URL = '/openapi/mp/developer/order/v1/report?';
    const REFUND_URL = '/openapi/mp/developer/epay/apply_refund?';
    const REFUND_QUERY_URL = '/openapi/mp/developer/epay/query_refund?';

    const REPORT_UPLOAD_URL = '/openapi/mp/developer/file//img/uploadWithUrl?';

    public function __construct($appId, $app_secret)
    {
        $this->appId = $appId;
        $this->secret = $app_secret;
        $this->httpClient = new HttpClient(8, 5);
        $this->cacheClass = Di::getDefault()->get('redis');
    }

    /**
     * 获取access_token
     * @param string $appid 如在类初始化时已提供，则可为空
     * @param string $appsecret 如在类初始化时已提供，则可为空
     * @param string $token 手动指定access_token，非必要情况不建议用
     */
    public function checkAuth($appid='', $appsecret='', $token='')
    {
        if (!$appid || !$appsecret) {
            $appid = $this->appId;
            $appsecret = $this->secret;
        }
        if ($token) { //手动指定token，优先使用
            $this->access_token=$token;
            return $this->access_token;
        }

        $authname = 'kuaishou_access_token'.$appid;
        if ($rs = $this->getCache($authname)) {
            $this->access_token = $rs;
            return $rs;
        }

        $result = $this->http_get(self::API_URL_PREFIX.self::AUTH_URL.'app_id='.$appid.'&app_secret='.$appsecret.'&grant_type=client_credentials');
        if (ENV_CLI == true) {
            var_dump($result, $appid, $appsecret);
        }
        Di::getDefault()->get('logger')->info("kuaishou_api access_token result is" . $result);
        if ($result) {
            $json = json_decode($result, true);

            if ($json && isset($json['result']) && $json['result'] == 1) {
                var_dump($json);
                $this->access_token = $json['access_token'];
                $expire = $json['expires_in'] ? intval($json['expires_in'])-100 : 3600;
                $this->setCache($authname, $this->access_token, $expire);
                return $this->access_token;
            }
        }
        return false;
    }

    /**
     * 设置缓存，按需重载
     * @param string $cachename
     * @param mixed $value
     * @param int $expired
     * @return boolean
     */
    protected function setCache($cachename, $value, $expired)
    {
        //TODO: set cache implementation
        return $this->cacheClass->set($cachename, $value, $expired);
    }

    /**
     * 获取缓存，按需重载
     * @param string $cachename
     * @return mixed
     */
    protected function getCache($cachename)
    {
        return $this->cacheClass->get($cachename);
    }

    /**
     * 清除缓存，按需重载
     * @param string $cachename
     * @return boolean
     */
    protected function removeCache($cachename)
    {
        return $this->cacheClass->del($cachename);
    }

    public function refund($orderNo, $refundOrderNo, $reason = '退款')
    {
        if (!$this->access_token && !$this->checkAuth()) {
            return false;
        }
        $body = [
            'app_id' => $this->appId,
            'out_order_no' => $orderNo,
            'out_refund_no' => $refundOrderNo,
            'reason' => $reason,
//            'notify_url' => self::REFUND_CALLBACK,
        ];

        $body['sign'] = $this->getSignContent($body);
        unset($body['app_id']);

        $url = self::API_URL_PREFIX. self::REFUND_URL . 'app_id='.$this->appId.'&access_token='.$this->access_token;

        $result = $this->httpClient->sendPostRequest($url, $body, [
            'Content-Type' => 'application/json',
        ]);
        $result = $result->getBody()->getContents();
        if (ENV_CLI) {
            var_dump($result);
        }
        
        Di::getDefault()->get('logger')->info("kuaishou_api refund request is " . $url . " body is" .json_encode($body) . " response is" . $result);
        if ($result) {
            $json = json_decode($result, true);
            if (isset($json['result']) && $json['result'] == 1) {
                return true;
            }
        }

        return false;
    }

    public function queryFundOrder($refundOrderNo)
    {
        if (!$this->access_token && !$this->checkAuth()) {
            return false;
        }
        $body = [
            'app_id' => $this->appId,
            'out_refund_no' => $refundOrderNo,
        ];

        $body['sign'] = $this->getSignContent($body);
        $url = self::API_URL_PREFIX. self::REFUND_QUERY_URL . 'app_id='.$this->appId.'&access_token='.$this->access_token;
        $result = $this->http_post($url, $body, array('Content-Type: application/json'));

        Di::getDefault()->get('logger')->info("kuaishou_api refund request is " . $url . " body is" .json_encode($body) . " response is" . $result);
        if ($result) {
            $json = json_decode($result, true);
            if (isset($json['result']) && $json['result'] == 1) {
                return $json;
            }
        }

        return false;
    }

    public function orderReport($body)
    {
        if (!$this->access_token && !$this->checkAuth()) {
            return false;
        }

        if (is_array($body)) {
            $body = json_encode($body);
        }

        $url = self::API_URL_PREFIX. self::REPORT_URL . 'app_id='.$this->appId.'&access_token='.$this->access_token;
        $result = $this->http_post($url, $body, array('Content-Type: application/json'));

        Di::getDefault()->get('logger')->info("kuaishou_api orderReport request is " . $url . " body is" .json_encode($body) . " response is" . $result);
        if ($result) {
            $json = json_decode($result, true);

            if (isset($json['result']) && $json['result'] == 1) {
                return true;
            }
        }

        return false;
    }

    /**
     * 快手担保支付签名处理
     * @param $params
     * @param $charset
     * @return string
     */
    private function getSignContent($postData) {
        $arr = $postData;
        // return $arr;
        foreach ($arr as $k => $item) {
            if (empty($item)) {
                unset($arr[$k]);
            }
        }
        ksort($arr, 2);
        $str = '';
        foreach ($arr as $k => $v) {
            $str .= $k . '=' . $v . '&';
        }
        $str = substr($str, 0, strlen($str) - 1);
        $md5 = $str .  $this->secret;
        return md5($md5);

    }

    public function uploadWithUrl($fileUrl)
    {
        if (!$this->access_token && !$this->checkAuth()) {
            return false;
        }
        if (strpos($fileUrl, "cdn.doumvip.com") !== false) {
            $fileUrl .= '?imageMogr2/thumbnail/512x512!';
        } elseif (strpos($fileUrl, "aliyuncs.com") !== false) {
            $fileUrl .= '?x-oss-process=image/resize,m_fill,h_512,w_512';
        }

        $url = self::API_URL_PREFIX. self::REPORT_UPLOAD_URL . 'app_id='.$this->appId.'&access_token='.$this->access_token;

        $result = $this->http_post($url, [
            'url' => $fileUrl,
        ]);

        Di::getDefault()->get('logger')->info("kuaishou_api uploadWithUrl request is " . $url . " response is" . $result);
        if ($result) {

            $json = json_decode($result, true);

            if (isset($json['result']) && $json['result'] == 1) {
                return $json['data']['imgId'];
            }
        }

        return false;
    }
    /**
     * GET 请求
     * @param string $url
     */
    private function http_get($url)
    {
        $oCurl = curl_init();
        if (stripos($url, "https://")!==false) {
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, false);
            curl_setopt($oCurl, CURLOPT_SSLVERSION, 1); //CURL_SSLVERSION_TLSv1
        }
        curl_setopt($oCurl, CURLOPT_URL, $url);
        curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1);
        $sContent = curl_exec($oCurl);
        $aStatus = curl_getinfo($oCurl);
        curl_close($oCurl);
        if (intval($aStatus["http_code"])==200) {
            return $sContent;
        } else {
            return false;
        }
    }

    /**
     * POST 请求
     * @param string $url
     * @param array $param
     * @param boolean $post_file 是否文件上传
     * @return string content
     */
    private function http_post($url, $param, $header=[], $post_file=false)
    {
        $oCurl = curl_init();
        if (stripos($url, "https://")!==false) {
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, false);
            curl_setopt($oCurl, CURLOPT_SSLVERSION, 1); //CURL_SSLVERSION_TLSv1
        }
        if (PHP_VERSION_ID >= 50500 && class_exists('\CURLFile')) {
            $is_curlFile = true;
        } else {
            $is_curlFile = false;
            if (defined('CURLOPT_SAFE_UPLOAD')) {
                curl_setopt($oCurl, CURLOPT_SAFE_UPLOAD, false);
            }
        }
        if (is_string($param)) {
            $strPOST = $param;
        } elseif ($post_file) {
            if ($is_curlFile) {
                foreach ($param as $key => $val) {
                    if (substr($val, 0, 1) == '@') {
                        $param[$key] = new \CURLFile(realpath(substr($val, 1)));
                    }
                }
            }
            $strPOST = $param;
        } else {
            $aPOST = [];
            foreach ($param as $key=>$val) {
                $aPOST[] = $key."=".urlencode($val);
            }
            $strPOST =  join("&", $aPOST);
        }
        curl_setopt($oCurl, CURLOPT_URL, $url);
        curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($oCurl, CURLOPT_POST, true);
        curl_setopt($oCurl, CURLOPT_POSTFIELDS, $strPOST);
        curl_setopt($oCurl,CURLOPT_HTTPHEADER,$header);

        $sContent = curl_exec($oCurl);
        $aStatus = curl_getinfo($oCurl);
        curl_close($oCurl);
        if (intval($aStatus["http_code"])==200) {
            return $sContent;
        } else {
            return false;
        }
    }
}
